fix(platform-objects): the es-ES and ja-JP dashboard gap help text says what its source now says - #16190
Conversation
…says what its source now says `metadataForms.dashboard.fields.gap.helpText` read `Separación de cuadrícula (unidades Tailwind)` in es-ES and 「グリッド間隔(Tailwind 単位)」 in ja-JP — faithful translations of `Grid gap (Tailwind units)`, a source sentence that no longer exists. The source now reads `Space between widgets, in steps of 0.25rem (4 = 1rem)`: it drops the CSS framework unit an app author never chose, and adds the magnitude the author needs to size a dashboard. Bundle merge fills gaps only, so a present-but-stale leaf is never corrected by re-extraction. Both leaves are rewritten by hand against the current English. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Ready to release — held only by a tooling channel, not by anything in this PRRecording this once rather than leaving the draft state unexplained. All three landing
⛔ The one remaining step — marking the PR ready for review — is only reachable through the ⇒ Nothing is wrong with this branch. The PM seat will retry on each check-in until it goes Generated by Claude Code |
Fixes #16165
Two leaves.
metadataForms.dashboard.fields.gap.helpTextin the es-ES and ja-JPmetadata-form bundles were faithful translations of a source sentence that no longer
exists.
Grid gap (Tailwind units)packages/spec/src/ui/dashboard.form.ts:25)Space between widgets, in steps of 0.25rem (4 = 1rem):943)Separación de cuadrícula (unidades Tailwind):943)Espacio entre widgets, en incrementos de 0.25rem (4 = 1rem):943):943)All three strings were re-located by text, not by the line numbers the card recorded.
On this branch's base
4e090ecdethe card's quotes and its line numbers both still hold:es-ES:943,ja-JP:943, English unmoved atdashboard.form.ts:25. The zh-CN round foundits line number eight rows stale, so this was checked rather than assumed; here it was not.
Why the wording
The new English does two things on purpose, and each replacement has to do both: drop the
CSS framework unit an app author never chose and cannot act on, and carry the magnitude
that lets the author size a dashboard. Every register call below was measured against the
bundle it lands in, not picked.
es-ES —
Espacio entre widgets, en incrementos de 0.25rem (4 = 1rem)de cuadrículagoes with
unidades Tailwind. The author is spacing widgets, not addressing a grid.widgets, notcomponentes. The loanword is what this bundle uses for dashboardwidgets — 7 occurrences (
Widgets del panel,Tarjetas y gráficos colocados en la cuadrícula.,Filtros aplicados a todos los widgets,Widgets del panel con posición y tamaño).componentealso appears in this file, 4 times, and every one of them is thepage-layout component concept (
Regiones de diseño … con componentes,Componente (por id) que escribe esta variable, theComponentelabel at:1133). Using it herewould collide with a different noun in the same bundle.
0.25remkeeps the ASCII decimal point. It is a CSS length literal the author types,not a quantity in prose. Measured in this file: the only decimal numbers are dot-form
(
Decimales (p. ej., 2 para $10.50)at:409) and there are zero comma-decimals, soa Spanish decimal comma would be new to this bundle as well as wrong as CSS.
en incrementos deoveren pasos de. This bundle has no precedent for either — 0hits for
paso, 0 forincremento— so the choice is general technical Spanish registerrather than a house style.
en incrementos deis the standard rendering for a quantisedscale;
en pasos dereads as a calque of the English words.(4 = 1rem)in half-width parens. 140 half-width parens in this file against 0full-width. The
=-inside-a-parenthetical shape is already the bundle's own way ofmapping an input value to its meaning:
(empty = forever)at:314,(one entry = locked)at:829,(blank = all object fields)at:837. Keeping=also preservesthe source's equation exactly, which is what a numeric conversion needs.
ja-JP — 「ウィジェット間の間隔、0.25rem 刻み(4 = 1rem)」
「ウィジェット間の間隔」. 「ウィジェット」 is this bundle's word throughout
(「グリッドに配置するカードとチャート。」, 「全ウィジェットに適用するフィルター」,
「位置とサイズを持つダッシュボードウィジェット」), and 「間隔」 is its word for spacing —
4 occurrences, including this field's own label 「間隔」. 「余白」 appears 0 times.
(「Tailwind 単位」); reusing it would read as swapping the framework name while keeping the
"unit" framing the English retired. It also means something else in this bundle — the
per-X granularity sense at
:988「アプリ単位」,:1471「オブジェクト単位」,:1514「フラットな単位」. 「刻み」 is the ordinary Japanese for a quantised step and carries no
such collision. It appears 0 times in this file today, so it introduces nothing that
contradicts an established choice.
three-part shape (head clause, step clause, parenthetical equation). 57 occurrences in
this file, including inside help text: 「一意識別子(snake_case、作成後は変更不可)」 at
:345, 「snake_case、environment ごとに一意」 at:647.half-width ones sit in code-ish or untranslated strings. Inside the
dashboardsubtreethe split is unanimous: 「(既定 12)」, 「(秒)」, 「(title, subtitle, actions)」 are all
full-width, so the immediate siblings decide it.
0.25rem 刻みfollows the bundle's ASCII/Japanese boundary spacing:「snake_case の一意識別子」, 「グリッド列(既定 12)」, 「BCP-47 タグ」, 「1 つの」.
helpTextentries in this bundle do not carry one (「グリッド列(既定12)」, 「自動更新(秒)」), while
descriptionentries do.The register model these two were matched against
The zh-CN sweep of this same subtree (
9f57f1e31, 2026-09-03) states in its own commitmessage that its replacements "mirror es-ES / ja-JP, both of which are correct at all five
leaves". So for this subtree es-ES and ja-JP are the reference register, not the followers,
and the job here was to keep them that way rather than to import a Chinese solution.
Verified independently rather than taken on that commit's word: all 13 other source-derived
prose leaves of
metadataForms.dashboard— 5 section descriptions and 8 further field helptexts — were read against the current English in both locales and every one tracks it.
gapis the only stale leaf. The English inventory the comparison used isen.metadata-forms.generated.ts:901..966, 14 prose leaves in total.No objectui overlay exists for either locale. Read at objectui
origin/main859de84:metadata-form-i18n.tsresolvesbundleLocale()to'zh-CN'for zh andundefinedforeverything else, and its own header says the metadata designer ships
enandzhand"the other eight shipped locales render the producer's English", so "this bundle carries
zh-CNonly". The zh-CN round matched that overlay's opening deliberately; here there isnothing to match, and this bundle is the only translated surface these two locales have for
this field. No objectui card is touched.
Four instruments are blind to this defect, and their green is not evidence
Re-run in this branch's worktree, exit codes captured by redirect-then-read, never through
a pipe. BEFORE is the same tree with both leaves reverted to the base, with the mutation
proven on disk by whole-line anchors and the restore proven afterwards by blob equality
against the HEAD blob plus an empty
git diff HEAD, all in one shell:The numbers are identical either side of the change, to the byte. That is the durable
half of this card: a green gate here is not evidence the change was needed, and not
evidence it worked.
check:i18nfills gaps only. It compares committed bundles against a freshextraction, and merge fills gaps — a present-but-stale leaf is not a gap, so
--writerewrites the
enleaf and leaves es-ES and ja-JP alone. Regeneration is structurallyincapable of fixing this.
check:i18n-stale-fillinfers a stale fill from cross-locale agreement. It catches aleaf that is a copy of the English wearing a translation's name.
Separación de cuadrícula (unidades Tailwind)and 「グリッド間隔(Tailwind 単位)」 are realtranslations, written by translators, agreeing with no other locale. Invisible to that
predicate by construction, not by accident.
There is no provenance to fall back on, verified per locale. Neither
es-ES.source-hashes.generated.tsnorja-JP.source-hashes.generated.tscarries adashboardentry — case-insensitive, real exit code 1, zero matching lines. The controlfires in the same files:
objectmatches 463 lines in the es-ES table and 454 in theja-JP one. And the miss is not that the table ignores this bundle: both tables do carry
metadataForms.*paths, 190 each, across 14 sibling subtrees (action,api,book,capability,dataset,doc,field,hook,mapping,object,page,report,seed,view).dashboardis simply not one of them, and per that file's own header"a path with no entry is LEGACY-TRUSTED and never reported stale".
The Docs Drift Check cannot anchor the changed symbol. Re-run locally against the
base, reading the JSON fields rather than the rendered comment
(
node scripts/docs-audit/affected-docs.mjs --json 4e090ecde):The name it could not anchor is
dashboard, notgap— the same reading the zh-CNround measured.
dashboardwas derived as an anchor candidate and dropped as a singlelowercase word;
gapwas never derived as a candidate at all, sinceanchorsis emptyand
weakAnchorsDroppedhas exactly one entry. No page documenting this leaf can surfacein that work list by either route.
Four independent instruments, none of them broken — each answers a different question
correctly, and this defect falls between all four.
The hand pass the drift check could not do
Searched
content/docsby hand, plain directory pathspec, fixed strings:Space between widgetsin steps of 0.25rem0.25remGrid gapTailwind unitsunidades TailwindSeparación de cuadrículacontrol, and the difference matters. Measured under the same pathspec:
dashboardmatches76 files and
refreshInterval2, so the pathspec works; but no Spanish or Japanese textexists in
content/docsat all —ción,áandñeach match 0 files, and so doー,日本,ダッシュボード,するand、, while the Chinese control的matches 4. So theright statement is the inventory one: there is no Spanish or Japanese documentation prose
in this tree for either stale string to be sitting in, rather than "a search that could have
found it found nothing".
The single English hit is
content/docs/references/ui/dashboard.mdx:36and needs nochange:
It already carries the current English, because that page is generated from
packages/spec/src/ui/dashboard.zod.tsand regenerates with it. The English documentationsurface was never stale; only the translations were. Nothing matched under
content/docs/releases/for any of the four English patterns, so nothing here goes nearrelease notes.
Scope
Two leaves, deliberately.
columnsis unchanged upstream, soColumnas de cuadrícula (predeterminado 12)and 「グリッド列(既定 12)」 stay accurate. The general sweep of thissubtree is objectstack#14931's and is not started here.
On the state of the zh-CN half: PR #16163 was open and unmerged when this branch was
cut and when this body was written, so on
mainthree leaves of this family are stale, nottwo — the correction triage posted on the card. This PR still fixes exactly the two it was
dispatched for; the zh-CN leaf belongs to #15511 and is untouched here. There is no
collision to coordinate: #16163's diff is
zh-CN.metadata-forms.generated.tsplus its ownchangeset, and this branch touches neither file, so the two merge independently even though
all three leaves sit at
:943of their respective files.Verification
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack→ 47 families, 55runnable commands, derived from the tree at
f54d139d3with the change set taken from themerge base
4e090ecde(three-dot, including the changeset file). 54 of 55 green, exitcodes captured by redirect before any pipe. Re-derived after the changeset landed; the
family did not grow.
pnpm --filter @objectstack/spec run check:react-declaration-parity,exit 1 with
MANIFEST is not set — there is no registry side to compare againstand itsown words "This gate did NOT run. That is a failure, not a skip". That is a prerequisite
refusal, NOT MEASURED locally, not a red about this diff — the manifest comes from an
objectui browser build that CI supplies, and this diff touches no file in
packages/spec.pnpm run buildfirst: 72 of 72 turbo tasks successful. It matters for what thesweeping gates then measured —
check:dts-closurereports 72 built packages swept,164/164 declared declaration files present, so its green is a statement about a
population that includes this package rather than about other packages.
pnpm --filter @objectstack/platform-objects test— 35 files, 528 tests passed.pnpm --filter @objectstack/platform-objects typecheck— clean, and the program wasproven to include the edited files rather than assumed to:
tsc --noEmit --listFileslists 419 files and both
es-ES.metadata-forms.generated.tsandja-JP.metadata-forms.generated.tsare among them.all 22 published declaration files byte-identical, while 12 of the 66 files
distpublishes did move in the same run —
index,metadata-translations/indexandpluginin both
.jsand.mjs, plus their six sourcemaps. That firing control is what makes thenegative a measurement rather than a blind spot. The rebuild is proven to have re-run by
mtimes advancing on all three legs, and
pnpm run buildwas invoked per package so noturbo cache sat on the path. Mutation proven on disk by whole-line anchors and proven to
have reached
dist(the retiredunidades Tailwindappears in 12 dist files whilemutated, in 0 after restore); restore proven by blob equality against the HEAD blob, an
empty
git diff HEAD, and a byte-for-byte re-comparison of all 66 dist files against thepre-ablation snapshot.
esESMetadataForms/jaJPMetadataFormsdata structures. The declaration side cannotmove for it by construction: the published subpath declares
declare const MetadataFormsTranslations: TranslationBundle;, an opaque bundle type, sono literal type carries any leaf text — neither locale constant is even named by symbol in
any of the 22 declaration files. No exported symbol, signature, or accept/reject behaviour
moves. That reading is declared in the card's claim comment, which is the carrier the
enqueue gate reads.
pnpm check:partof-closing-keywordpassed in the sweep on an emptyPR_BODY, which isa vacuous pass by that gate's design — it reads the body from the environment and never
from the API. It was re-run against this posted body afterwards; that run is the reading.
Changeset rather than the
skip-changesetlabel, re-derived rather than carried over:@objectstack/platform-objectsdeclares noprivateflag and publishesdist, and thesestrings reach Spanish- and Japanese-reading Studio authors, so the diff does publish
something.
patch, matching the sibling sweeps for the same subtree.Authored by Claude Code session
session_01ARYe3yQTQCUFm5qPYNgKaJ— attribution kept inprose because a body edit downgrades the session-scoped footer link to the bare form.
Generated by Claude Code